import java.util.LinkedList;
import java.util.List;

public class Jugador {

	/**
	 * @uml.property  name="nombre"
	 */
	private String nombre;
	/**
	 * @uml.property  name="mazo"
	 * @uml.associationEnd  inverse="jugador:Mazo"
	 */
	private Mazo<CartaJugador> jugada;
	/**
	 * @uml.property  name="posicionActual"
	 * @uml.associationEnd  inverse="jugador:CasillaCiudad"
	 */
	private CasillaCiudad posicionActual;

	private Roles rol;

	public Jugador(String nombre,CasillaCiudad posicionActual,Roles rol){
		this.nombre = nombre;
		this.posicionActual = posicionActual;
		this.jugada = new Mazo<CartaJugador>();
		this.rol= rol;
	}

	/**
	 * Getter of the property <tt>nombre</tt>
	 * @return  Returns the nombre.
	 * @uml.property  name="nombre"
	 */
	public String getNombre() {
		return nombre;
	}

	/**
	 * Setter of the property <tt>nombre</tt>
	 * @param nombre  The nombre to set.
	 * @uml.property  name="nombre"
	 */
	public void setNombre(String nombre) {
		this.nombre = nombre;
	}

	/**
	 * Getter of the property <tt>mazo</tt>
	 * @return  Returns the mazo.
	 * @uml.property  name="mazo"
	 */
	public Mazo<CartaJugador> getJugada() {
		return jugada;
	}

	/**
	 * Setter of the property <tt>mazo</tt>
	 * @param mazo  The mazo to set.
	 * @uml.property  name="mazo"
	 */
	public void setJugada(Mazo<CartaJugador> mazo) {
		this.jugada = mazo;
	}

	/**
	 * Getter of the property <tt>posicionActual</tt>
	 * @return  Returns the posicionActual.
	 * @uml.property  name="posicionActual"
	 */
	public CasillaCiudad getPosicionActual() {
		return posicionActual;
	}

	/**
	 * Setter of the property <tt>posicionActual</tt>
	 * @param posicionActual  The posicionActual to set.
	 * @uml.property  name="posicionActual"
	 */
	public void setPosicionActual(CasillaCiudad posicionActual) {
		this.posicionActual = posicionActual;
	}

	public Roles getRol(){
		return this.rol;
	}

	private void actualizaPosicionActual(CasillaCiudad cconducir, CartaCiudad carta,int direccion) {
		if(cconducir!=null) posicionActual=cconducir;
		if(carta!=null)  posicionActual=Tablero.casillasCiudades.get(carta.getCiudad().getCodigo());
		if(direccion>=0) posicionActual=Tablero.casillasCiudades.get(direccion);
	}

	public CartaCiudad getCartaCiudadJugada(){
		for(int i=0;i<jugada.MazoSize();i++){
			if(jugada.getCartaPorIndice(i) instanceof CartaCiudad && jugada.getCartaPorIndice(i).getCiudad().equals(posicionActual.getCiudad()))
				return (CartaCiudad) jugada.getCartaPorIndice(i);
		}
		return null;
	}

	public void conducir(){
		System.out.println("*****************CONDUCIR O TOMAR UN FERRY*******************");
		System.out.println("Estas en "+posicionActual.getCiudad());
		Tablero.imprimirCiudadesAdyacentes(posicionActual);
		System.out.println("Elige ciudad: ");
		int direccion=Pandemic.leer(posicionActual.getAdyacentes().size());
		CasillaCiudad cconducir=posicionActual.getAdyacentes().get(direccion);
		actualizaPosicionActual(cconducir,null,-1);
		System.out.println("**********************************************");
	}

	public boolean vueloDirecto(Mazo<CartaJugador> mazoJugadorDescartado){
		boolean tienecartaciudad=false;
		if(jugada.MazoSize()!=0){//si tiene cartas en mano
			System.out.println("***************VUELO DIRECTO********************");
			System.out.println("A que ciudad quieres volar?");
			for(int i=0;i<jugada.MazoSize();i++){
				if(jugada.getCartaPorIndice(i) instanceof CartaCiudad){//da a elegir entre las cartas de ciudad
					System.out.println(i+") Ciudad: "+jugada.getCartaPorIndice(i).getCiudad().toString());
					tienecartaciudad=true;
				}
			}
			System.out.println("Elige ciudad: ");
			int direccion=Pandemic.leer(jugada.MazoSize());
			CartaCiudad cvuelodirecto=(CartaCiudad) jugada.getCartaPorIndice(direccion);
			mazoJugadorDescartado.robaMazo(cvuelodirecto,jugada);//descarta
			actualizaPosicionActual(null,cvuelodirecto,-1);
			System.out.println("**********************************************");

		}
		if(!tienecartaciudad){//si no tiene cartas o de las que tiene ninguna es de ciudad
			System.out.println("**********************************************");
			System.out.println("Lo siento no puedes volar a ningun sitio");
			System.out.println("**********************************************");
			return false;
		}
		else return true;
	}

	public boolean vueloCharter(Mazo<CartaJugador> mazoJugadorDescartado){
		CartaCiudad cvuelocharter=null;
		boolean tienecartaciudad=false;
		if(jugada.MazoSize()!=0){//si tiene cartas en mano
			System.out.println("**************VUELO CHARTER*******************");
			System.out.println("�A que ciudad quieres volar?");
			for(int i=0;i<jugada.MazoSize();i++){
				if(jugada.getCartaPorIndice(i) instanceof CartaCiudad){//tiene q tener la carta de la posicion actual
					if (jugada.getCartaPorIndice(i).getCiudad().equals(posicionActual.getCiudad())){
						cvuelocharter=(CartaCiudad)jugada.getCartaPorIndice(i);
						Tablero.imprimirCiudades();
						System.out.println("Elige ciudad: ");
						int direccion=Pandemic.leer(Tablero.casillasCiudades.size());
						mazoJugadorDescartado.robaMazo(cvuelocharter,jugada);//descarta
						actualizaPosicionActual(null,null,direccion);
						tienecartaciudad=true;
					}
				}
			}
			System.out.println("**********************************************");
		}
		if(!tienecartaciudad){//si no tiene cartas o de las que tiene ninguna es de ciudad
			System.out.println("**********************************************");
			System.out.println("Lo siento no puedes volar a ningun sitio");
			System.out.println("**********************************************");
			return false;
		}
		else return true;
	}

	public boolean vueloPrivado(){
		if(Tablero.centrosInvestigacion.contains(getPosicionActual()) && Tablero.centrosInvestigacion.size()!=1){
			System.out.println("**************VUELO PRIVADO*******************");
			System.out.println("�A que ciudad quieres volar?");
			Tablero.imprimirCentrosInvestigacion();
			int direccion=Pandemic.leer(Tablero.centrosInvestigacion.size());
			actualizaPosicionActual(null,null,direccion);
			System.out.println("**********************************************");
			return true;
		}
		else{
			System.out.println("**********************************************");
			System.out.println("Lo siento no puedes volar a ningun sitio");
			System.out.println("**********************************************");
			return false;
		}
	}

	//acciones especiales de Jugador

	public boolean construirCentroInvestigacion(Mazo<CartaJugador> mazoJugadorDescartado){
		boolean construido=false;
		System.out.println("*******************************************************");
		if(!CasillaCiudad.tieneCentro(posicionActual)){
			if(Tablero.centrosInvestigacion.size()<Tablero.maxCentrosInvestigacion){
				//descarta la carta de la posicion actual y construye el centro
				if(getCartaCiudadJugada()!=null){
					Tablero.centrosInvestigacion.add(posicionActual);
					mazoJugadorDescartado.robaMazo(getCartaCiudadJugada(),jugada);//descarta
					construido=true;
				}
			}
			else{
				//como ya estan construidos el max de centros, mueve uno a la ciudad donde esta el jugador
				if(getCartaCiudadJugada()!=null){
					System.out.println("Se ha alcanzado el maximo de centros construidos, elige uno de la lista para moverlo a tu posicion");
					Tablero.imprimirCentrosInvestigacion();
					int opcion=Pandemic.leer(Tablero.centrosInvestigacion.size());
					Tablero.centrosInvestigacion.set(opcion,posicionActual);
					mazoJugadorDescartado.robaMazo(getCartaCiudadJugada(),jugada);//descarta
					construido=true;
				}
			}
		}else System.out.println("Lo siento tu posicion actual ya tiene un centro de investigaci�n");

		if(!construido && getCartaCiudadJugada()==null) System.out.println("Lo siento no tienes la carta de tu posicion "+posicionActual.getCiudad());
		else{
			System.out.println("Centro de investigacion construido en "+posicionActual.getCiudad()+"!!!!");
		}
		System.out.println("*******************************************************");
		return construido;
	}

	public boolean descubrirCura(Mazo<CartaJugador> mazoJugadorDescartado,int cartasnecesarias){
		int numcartas=0;
		Color color;
		int opcion;
		Carta carta;
		List<Integer> indices=new LinkedList<Integer>();
		List<CartaCiudad> cartasparadescartar=new LinkedList<CartaCiudad>();
		List<Color> colores=new LinkedList<Color>();
		boolean descubierta=false;
		System.out.println("*******************************************************");
		if(CasillaCiudad.tieneCentro(posicionActual)){
			System.out.println("�Que tipo de cura quieres descubrir?");
			int i=0;
			for(Color c:Color.values()){
				System.out.println(i+") CURA COLOR: "+c);
				colores.add(c);
				i++;
			}
			opcion=Pandemic.leer(Color.values().length);
			color=colores.get(opcion);

			if(!Tablero.curasDescubiertas.contains(color)){
				for(int j=0;j<jugada.MazoSize();j++){
					carta=jugada.getCartaPorIndice(j);
					if(carta instanceof CartaCiudad)
						if(carta.getColor().equals(color)) {
							indices.add(j);
							numcartas++;
						}
				}
				if(numcartas>=cartasnecesarias){//son al menos 5 y del color elegido por el jugador
					System.out.println("Elige una a una las cartas a descartar: ");
					for(int limite=cartasnecesarias;limite!=0;limite--){
						System.out.println("Quedan "+limite+" cartas por descartar");
						for(int k=0;k<numcartas;k++)
							System.out.println(k+") Ciudad: "+jugada.getCartaPorIndice(indices.get(k)).getCiudad()+" Color: "+jugada.getCartaPorIndice(indices.get(k)).getColor());
						opcion=Pandemic.leer(numcartas);
						cartasparadescartar.add((CartaCiudad) jugada.getCartaPorIndice(indices.remove(opcion)));
						numcartas--;
					}
					mazoJugadorDescartado.getMazo().addAll(cartasparadescartar);
					jugada.getMazo().removeAll(cartasparadescartar);
					Tablero.curaDescubierta(color);
					descubierta = true;
					System.out.println("CURA COLOR "+color+" DESCUBIERTA!!!");
				}else System.out.println("No tienes las cartas necesarias para descubrir la cura "+color);
			}else System.out.println("Esa cura ya esta descubierta!!!");
		}else System.out.println("No hay un centro de investigacion en tu posicion "+posicionActual.getCiudad());
		System.out.println("*******************************************************");
		return descubierta;
	}

	public boolean tratarEnfermedad(boolean esmedico){
		System.out.println("*******************************************************");
		boolean desinfectada=false;
		if(posicionActual.infectada()){
			//elegir el color a desinfectar
			System.out.println("Ciudad: "+posicionActual.getCiudad());
			posicionActual.imprimirInfecciones();
			int opcion=Pandemic.leer(Color.values().length);
			Color color=Color.values()[opcion];
			//si la posicion actual esta infectada con el color elegido
			if(posicionActual.getNivelesInfeccion().get(color).getNivel()>0){
				//si es medico o la cura del color elegido ha sido encontrada quitar todos los cubos
				if((esmedico || Tablero.curasDescubiertas.contains(color))){
					//desinfecto indicando que quite todos los cubos del color elegido
					posicionActual.desinfectar(true,color);
				}
				//si no es medico y no se ha descubierto la cura del color elegido quita un cubo
				else if((!esmedico && !Tablero.curasDescubiertas.contains(color))){
					posicionActual.desinfectar(false,color);

				}
				desinfectada=true;
				System.out.println("Infeccion de color "+color+" tratada en "+posicionActual.getCiudad()+"!!!");
				posicionActual.imprimirInfecciones();
			}
			else{
				System.out.println("Tu posicion no esta infectada con el color: "+color);
				posicionActual.imprimirInfecciones();
			}
		}else{
			System.out.println("Tu posicion no esta infectada: "+posicionActual.getCiudad());
		}
		System.out.println("*******************************************************");
		return desinfectada;
	}

	public boolean compartirConocimientos(List<Jugador> jugadores,Mazo<CartaJugador> mazoJugadorDescartado,boolean esinvestigador){
		boolean compartida=false;
		CartaCiudad carta;
		//si es el investigador debe elegir q carta da
		//si no es el investigador veo si tiene la carta de la posicion actual
		if(esinvestigador) carta=(CartaCiudad) ((JugadorInvestigador) this).accionEspecial();
		else carta=getCartaCiudadJugada();

		List<Integer> indices=new LinkedList<Integer>();
		if(carta!=null || esinvestigador){
			System.out.println("Elige a que jugador le das la carta: Ciudad:" +carta.getCiudad()+" Color: "+carta.getColor());
			int j=0;
			for(int i=0;i<jugadores.size();i++){
				//muestra los jugadores q estan en la ciudad, excluye al actual
				if(jugadores.get(i).getPosicionActual().equals(posicionActual) && !this.equals(jugadores.get(i))){
					System.out.println(j+") Jugador "+jugadores.get(i).getNombre()+" "+jugadores.get(i).getRol());
					indices.add(i);
					j++;
				}
			}
				//si hay otros jugadores en la misma ciudad elige a cual se le da la carta
			if(indices.size()!=0){
				int opcion=Pandemic.leer(indices.size());
				/**/jugadores.get(indices.get(opcion)).robarCarta(carta,getJugada(),mazoJugadorDescartado);
				System.out.println("Le has dado la carta "+carta.getCiudad()+" "+carta.getColor()+" al jugador "+jugadores.get(indices.get(opcion)).getNombre());
				compartida=true;
			}
			else System.out.println("Lo siento no hay ningun jugador en tu posicion");

		}
		if(carta==null) System.out.println("Los siento no tienes la carta de tu posicion: "+posicionActual.getCiudad());
		if(carta==null && esinvestigador) System.out.println("Los siento, como investigador necesitas al menos una carta de ciudad");
		return compartida;
	}

	/**///este metodo es cuando se comparten conocimientos
	private void robarCarta(CartaCiudad carta,Mazo<CartaJugador> jugada, Mazo<CartaJugador> mazojugadordescartado){
		if(getJugada().MazoSize()<7){
			//si puede aceptar la carta directamente, se la roba al compa�ero que le pasa su jugada
			getJugada().robaMazo(carta,jugada);
		}
		else{//si tiene 7 tiene que descartar una
			List<Integer> indices=new LinkedList<Integer>();
			if(getJugada().MazoSize()!=0)
			{
				System.out.println("Jugador "+getNombre()+" "+getRol()+" tienes que descartar una carta:");
				int j=0;
				for(int i=0;i<getJugada().MazoSize();i++){
					if(getJugada().getCartaPorIndice(i) instanceof CartaCiudad){
						System.out.println(j+") Ciudad: "+getJugada().getCartaPorIndice(i).getCiudad()+" Color: "+getJugada().getCartaPorIndice(i).getColor());
						indices.add(i);
						j++;
					}
				}
				int opcion=Pandemic.leer(indices.size());
				System.out.println("Has descartado: "+getJugada().getCartaPorIndice(indices.get(opcion)).getCiudad()+" "+getJugada().getCartaPorIndice(indices.get(opcion)).getColor());
				mazojugadordescartado.robaMazo(getJugada().getCartaPorIndice(indices.get(opcion)),getJugada());
				getJugada().robaMazo(carta,jugada);
			}
		}
	}

	public void imprimirJugada(){
		System.out.println("**********************************************");
		System.out.println("Las cartas de "+this.nombre+" son:");
        if (jugada.MazoSize()==0) System.out.println("No tienes cartas.");
		for(int k=0;k<jugada.MazoSize();k++){
          	 if(jugada.getCartaPorIndice(k) instanceof CartaCiudad)
          		 System.out.println("Ciudad: "+jugada.getCartaPorIndice(k).getCiudad().toString()+" Color: "+jugada.getMazo().get(k).getColor().toString());
          	 if(jugada.getCartaPorIndice(k) instanceof CartaEventoEspecial){
          		System.out.println("Evento Especial: "+((CartaEventoEspecial) jugada.getCartaPorIndice(k)).getEventoEspecial());
          	 }
          	if(jugada.getCartaPorIndice(k) instanceof CartaEpidemia){
          		System.out.println("EPIDEMIA!!!");
          	 }
        }
        System.out.println("**********************************************");
        System.out.println(" ");
	}

}
